Introduction

WebWriter++ tries to meet a number of objectives in allowing authors to present code to students—

  1. The code should be presented in a fashion familiar to students. Typically, this means syntax-staining the code in a manner that is as close to the way their editor does it as possible.
  2. The code should be exportable to the Teaching Machine.
  3. The code should be isolated in a separate, compilable file, to allow an instructor to check for syntax and even debug it.
  4. Markup techniques available in the WebWriter++ toolset should be available for use with code.

It might seem that syntax-staining (1) and code mark-up (4) would be incompatible with the other two objectives. However, (1) is easily achieved by importing the source code and parsing and staining it on the fly. This feature was included in the toolset, which leaves only the fourth objective.

Enter pedagogical mark-up which is a small language that allows certain WebWriter++ calls to be embedded in C/C++ comments.

Supported Tools

Currently, the following tools are supported:

Indeed, pop-ups and rollover blocks were initially developed specifically to enable the marking of code.

Syntax

General

All mark-ups must appear inside C-style (multi-line) comments ('/* */'). Currently WebWriter++ is unforgiving about white space so that pedagogical markups must occur immediately after (and before) the comment operators, as follows:

		/*#p="integerPopup"*/int/*#/p*/ count = 0;	

Here, the keyword int has been marked as a pop link. The #p="integerPopup" command (which is wrapped in comment characters with no intervening spaces) declares that a pop link (which will call up a pop-up named integerPopup) starts at the keyword. Similarly, #/p marks the end of the link. Thus, the int keyword will appear as a link to the integerPopup when the code is displayed by WebWriter++.

Popups

   /*#P="popupName" "The text for the popUp"*/

Creates the pop-up. While html is allowed it does not currently work. A pop-up only has to be defined once (on a particular page). It can be linked multiple times. If you want cross-site pop-ups, use definitions and put them in the dictionary.

   /*#p="popupName"*/

Marks the beginning of a pop-up link. The "popupName" should be the name of the pop-up you want to see appear when the link is rolled over.

    /*#/p*/

Terminate a pop-up link.

Rollover Blocks

   /*#B="blockName"*/

Starts the block. The background colour of the block will change when its link is rolled over. Blocks may be wholly nested within each other.

    /*#/B*/

Terminate a block.

   /*#b="blockName"*/

Marks the beginning of a rollover block link. The "blockName" should be the name of the rollover block you want to see illuminated when the link is rolled over.

    /*#/b*/

Terminate a rollover block link.

Definitions

   /*#d="definitionName"*/

Marks the beginning of a definition link. The "definitionName" should be the name of the definition you want to see pop-up when the link is rolled over. Definitions are kept in a separate, standard dictionary.

    /*#/d*/

Terminate a definition link.

Selections

   /*#DX*/

Marks the beginning of a section of code to be displayed in the X selection where 'X' is any lette (or none). If no letter exists then all code after the command (until a hide command) is displayed. If there is a letter, then the code is only displayed if the TM is invoked with that letter as an argument.

/*#HX*/

Marks the beginning of a section of code to be hidden in the X selection where 'X' is any lette (or none). If no letter exists then all code after the command (until a display command) is displayed. If there is a letter, then the code is only hidden if the TM is invoked with that letter as an argument.

The default is to display all code. Thus if you want to display only certain sections of code in a TM selection you should start out by turning off code. For example, here is the some of the raw code for a complex example regarding inheritance with three separate selections, 'A', 'B' and 'C'. In the beginning each section is turned off individually. This is so that when the code is actually run in the TM it will be displayed, since the TM is normally set to display all (and thus displays everything unless all are turned off).

/*#HA*/ /*#HB*/ /*#HC*/class MyString{
public:
  MyString(char* p);	// Construct using a standard string
  MyString();			// "default" (no arguement) constructor
  MyString(MyString& orig);		// Copy constructor
  ~MyString();		// standard destructor to deal with heap

// Accessor functions - used to read object data without changing it
  int length() ;
  char getChar(int i) ;	// get char at location i
  void get(char* buff) ;	// Get the string & put it into user buff
  bool compare(MyString& other);	// true if equal
  
// Mutator functions - used to change string objects
  void setChar(int i, char c); // Change char at i to c
  void changeTo(char* newString);	// Change the whole string
  
/* Notice the change to pass by ref to improve efficiency */
  void changeTo(MyString& newString);	// Function overload

private:
  char* mPtr;	// pointer into the heap where the actual string will be
  int mLength;	// length of the string
  };

/*#DA*/ // A class of users for network management
class User{
public:
  User(char* n, char* u, char* p);

// Accessors
  MyString& name();	// return reference
  int allocation();	// Disk space allowed
  MyString password();	// return value
  MyString uname() ;
  bool confirm(MyString& uName, MyString& pass);

// Mutators
  bool setPassword(MyString& p1, MyString& p2);
  void setAllocation(int a);

protected: MyString mName; // Notice attributes that are OBJECTS! MyString mUname; MyString mPassword; int mAllocation; // Memory allocation, in MBytes };/*#HA*/ /*#DB*/class Student: public User{ public: Student(char* n, char* id, char* u, char* p); MyString id(); void buy(long amount); bool approvePrint(int pages); protected: MyString mId; long mPrintPennies; };/*#HB*/ /*#DC*/class Faculty: public User{ public: Faculty(char* n, char* u, char* p, char* today);

// accessor functions long pages(); MyString cleared(); // mutator functions bool approvePrint(int pages); // increases page count void clear(char* d); // clears count & notes date protected: long mPages; // Pages used since MyString mCleared; // last date cleared };/*#HC*/

To expose only class User, the Teaching Machine is invoked on selection "A", using the insertCode command, defined as follows:

function insertCode("userInherit.cpp", true, "code", "default.cfg", "A")

Mark-Up Removed for Presentation

While pedagogically marked code compiles just fine it is still messy and confusing for students to look at. Consequently, both WebWriter++ and the Teaching Machine automatically remove pedagogical markups from their displays.